import { Component, Injector, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, TemplateRef, ViewChild } from '@angular/core';
import { forEach as _forEach, remove as _remove } from 'lodash-es';
import { DateTime } from 'luxon';
import {
    ExternalSingleUploadMergeInput,
    ExternalSingleUploadVerifyInput,
    FileObjectConfigDto,
    FileUploadServiceProxy,
    MultipartUploadServiceProxy,
    SelectFromLibraryInput
} from "@shared/service-proxies/service-proxies";
import { AppConsts } from '@shared/AppConsts';
import { finalize } from 'rxjs/operators';
import { FileUploader, FileUploaderOptions, FileItem } from 'ng2-file-upload';
import { IAjaxResponse, TokenService, MessageService } from 'abp-ng2-module';
import { FileUploadHelper } from '@shared/helpers/FileUploadHelper';
import { AppLocalizationService } from '../localization/app-localization.service';
import { UploadItemData } from './upload-Item-data';
import { AppNotifyService } from '@shared/utils/service/app-notify.service';
import { FileUpdateModalComponent } from './file-update-modal.component';
import { AppBsModalService } from '@shared/common/appBsModal/app-bs-modal.service';
import { FileRenameModalComponent } from './file-rename-modal.component';
import { FindingFileItem } from '../file-finder/file-finder-options';
import { Status } from '../multipart-upload/multipart-upload-option';
import { MultipartUploadHelper } from '../multipart-upload/multipart-upload-helper';

@Component({
    selector: 'single-upload',
    templateUrl: './single-upload.component.html'
})
export class SingleUploadComponent implements OnInit, OnChanges{

    @Input() contentId: string;
    @Input() customKey: string;
    @Input() ctrlDisabled: boolean;
    @Input() alias: string;
    @Input() description: string;
    @Input() isTemporary: boolean = false;

    permission: boolean = false;
    config: FileObjectConfigDto;

    fileInfo: UploadItemData; // 文件信息
    remoteUrl: string;
    remoteSmallUrl: string;
    remoteDownUrl: string;

    private _multipartUploadHelper: MultipartUploadHelper;

    get showProgressBar(){
        return this._multipartUploadHelper.showHashProgress || this._multipartUploadHelper.showMerging
         || [Status.pause, Status.uploading, Status.error].includes(this._multipartUploadHelper.status);
    }

    get uploadProgress(): number {
		return this._multipartUploadHelper.uploadProgress;
	}

    @ViewChild('fileUpdateModal') fileUpdateModal: FileUpdateModalComponent;

    constructor(
        private _fileUploadServiceProxy: FileUploadServiceProxy,
        private _tokenService: TokenService,
        private message: MessageService,
        private notify: AppNotifyService,
        private _appLocalizationService: AppLocalizationService,
        private _modalService: AppBsModalService,
        private _multipartUploadService: MultipartUploadServiceProxy
    ) {
        this.fileInfo = new UploadItemData();
        this.config = new FileObjectConfigDto();

        this._multipartUploadHelper = new MultipartUploadHelper(notify, _tokenService);
    }

    ngOnInit(): void {
        this.permission = !this.ctrlDisabled;
        
        this.InitializeUpload();
    }

    private InitializeUpload() {
        this._multipartUploadHelper.Initialize(4, {
            uploaderUrl: AppConsts.remoteServiceBaseUrl + '/B/FileUpload/SingleUpload',
            partUploaderUrl: AppConsts.remoteServiceBaseUrl + '/B/EditorFile/PartUpload',
            singleUploaderOnBuildItemForm: (fileItem, form) => {
                form.append('contentId', this.contentId);
                form.append('customKey', this.customKey);
                form.append('alias', this.config.alias);
                form.append('isTemporary', this.isTemporary);
            },
            uploadedCallback: (fileItem) => {
                var data = new UploadItemData();
                data.init(fileItem);
                this.fileInfo = data;
                this.updateData();
            },
            verifyFunction: (t) => {
                return this._multipartUploadService.externalSingleUploadVerify(t);
            },
            getVerifyInput: (fileContainer) => {
                return new ExternalSingleUploadVerifyInput({
                    fileHash: fileContainer.hash,
                    fileName: fileContainer.file.name,
                    isTemporary: this.isTemporary,
                    contentId: this.contentId,
                    customKey: this.customKey,
                    alias: this.alias
                });
            },
            getMergeRequestInput: () => {
                return new ExternalSingleUploadMergeInput({
                    fileHash: this._multipartUploadHelper.container.hash,
                    fileName: this._multipartUploadHelper.container.file.name,
                    fileSize: this._multipartUploadHelper.container.file.size,
                    dimensions: this._multipartUploadHelper.container.dimensions,
                    count: this._multipartUploadHelper.chunks.length,
                    isTemporary: this.isTemporary,
                    contentId: this.contentId,
                    customKey: this.customKey,
                    alias: this.alias
                });
            },
            mergeRequestFunction: (t) => {
                return this._multipartUploadService.externalSingleUploadMerge(t);
            }
        });
    }

    ngOnChanges(changes: SimpleChanges): void {
        if (changes['contentId']) {
            if (this.contentId && this.customKey) {
                this.getConfig();
            }
        }

        if (changes['ctrlDisabled']){
            this.permission = !this.ctrlDisabled;
        }
    }
    getConfig() {
        this._fileUploadServiceProxy.getSingleConfigInfo(this.alias, this.customKey)
            .subscribe(result => {
                this.config = result;

                //自定义
                if (this.alias) {
                    this.config.alias = this.alias;
                }
                
                if (this.description) {
                    this.config.description = this.description;
                }
                
                this.initFile();
        });
    }

    initFile() {
        this._fileUploadServiceProxy.getFileInfo(this.contentId, this.config.alias)
            .subscribe(result => {
                this.fileInfo = new UploadItemData(result);
                this.updateData();
            });
    }

    //----文件上传-----

    fileChangeEvent(event: any): void {
        if (!this.permission || this._multipartUploadHelper.status === Status.uploading) {
            event.target.value = null;
            return;
        }

        if (event.target.files && event.target.files.length > 0) {
            let file = event.target.files[0];
            event.target.value = null;
            if (!FileUploadHelper.check(file.name, this.config.exNames, file.size, 
                this.config.maxSize, this.notify, this._appLocalizationService)) {
                
                let item = this._multipartUploadHelper.getUploadingFileItem(file);
                this._multipartUploadHelper.uploadingFileQueue.push(item);
                this._multipartUploadHelper.handleUpload();
            }
        }
    }

    //----文件上传 end-----

    private getUrl() {
        return FileUploadHelper.getUrl(this.fileInfo.fileUrl);
    }
    private getDownUrl() {
        return FileUploadHelper.getDownUrl(this.fileInfo.exName, this.fileInfo.fileUrl);
    }

    private getSmallUrl() {
        return FileUploadHelper.getSmallUrl(this.fileInfo.fileUrl, 100, 80);
    }

    
    lookOver(picurl:string) {
        abp.event.trigger(AppConsts.EventName.showImageView, picurl);
    }
    
    private updateData() {
        this.fileInfo.icon = FileUploadHelper.getIcon(this.fileInfo.exName);
        this.remoteSmallUrl = this.getSmallUrl();
        this.remoteUrl = this.getUrl();
        this.remoteDownUrl = this.getDownUrl();
    }

    //--- Actions

    update(id: string) {
        const bsModalRef = this._modalService.show(FileUpdateModalComponent, {
            backdrop: 'static', class: 'modal-lg'
        });
        bsModalRef.content.configure({
            id: id,
            customKey: this.customKey,
            multiply: false,
            autoSyncBySelf: false,
            config: this.config
        });
        bsModalRef.content.shown();
        bsModalRef.content.reloadList = () => {
            this.initFile();
        };
    }

    delete(id: string) {
        this.message.confirm(this._appLocalizationService.l("YesDelete"), null, (isConfirmed) => {
            if (isConfirmed) {
                this._fileUploadServiceProxy.deleteFile(id, this.customKey)
                    .subscribe(result => {
                        this.initFile();
                    });
            }
        });
    }

    pickupFile(){
        abp.event.trigger('abp.ckeditor.filefinder', { editor:null, multiSelect: false, callback: (list: FindingFileItem[])=>{
            if(list.length > 0){
                let item = list[0];
                let fileUrl = item.fileUrl;
                let fileName = item.fileName;

                if (!FileUploadHelper.checkExName(fileName, this.config.exNames)) {
                    let exNameArr = this.config.exNames.split('|');
                    this.notify.error(fileName + '：' + this._appLocalizationService.l('File_Invalid_Type_Error', exNameArr.join('、')));
                    return;
                }

                let input = new SelectFromLibraryInput({
                    alias : this.config.alias,
                    customKey :this.customKey,
                    fileUrl: fileUrl, 
                    contentId: this.contentId,
                    fileLength: item.size,
                    sha1: item.sha1,
                    isTemporary : this.isTemporary,
                    dimensions: item.dimensions
                });
                this._fileUploadServiceProxy.singleUpload2(input)
                    .subscribe(result=>{
                        var data = new UploadItemData();
                        data.init(result);
                        this.fileInfo = data;
                        this.updateData();
                    });
            }
        } });
    }

    reNameFile(id: string) {
        const strArr = this.fileInfo.fileName.split(".");
        const originName = strArr[0];
        const bsModalRef = this._modalService.show(FileRenameModalComponent, {
            backdrop: 'static'
        });
        bsModalRef.content.configure({
            id: id,
            originName: originName
        });
        bsModalRef.content.shown();
        bsModalRef.content.reloadList = () => {
            this.initFile();
        };
    }
}
